#include <stdio.h>
#include <stdlib.h>
#include "slave.h"
#include <assert.h>
#include "args.h"
#include "aceMesh_utils.h"
#include "aceMesh_task.h"
#include "aceMesh_runtime.h"
#include "helper_slave.h"


__thread_local volatile int helper_init_done=0;
__thread_local_fix int construct_end=0;
__thread_local int close_helper=0;  //需要用__thread_local int定义，用普通unsigned int 定义不行
// __thread_local int close_helper[64]={0};  //需要用__thread_local int定义，用普通unsigned int 定义不行
extern __thread_local int helper_exited[64];
__thread_local_fix int over=0;
// __thread_local struct MemPool slave_pool_ldm;
__thread_local_fix int collision_item_count;
#ifdef DISTRIBUTE_TOP
//每个helper一个latent_top
extern __thread_local_fix struct top_level_buff tl_buffer[NT];
// extern __thread_local struct top_level toptask; 
__thread_local_fix int topnum=0;
#endif
// __uncached volatile int slave_init_done=0;
__thread_local_fix struct slave_help_buff slave_buffer[NT];
#define remote_ldm(coreid,ldm_var) ((unsigned long)&ldm_var | ((unsigned long)coreid << 20 ) |(1ULL << 45))
#ifdef ACEMESH_GRAPH_BUILD_PROFILING
#ifdef FINE_PROF
// extern double all_pure_register_time[64];
extern double all_pure_addsucc_time[64];
__thread_local_fix double add_succ_start=0.0;
__thread_local_fix double add_succ_end=0.0;

extern double all_pure_register_time[64];
__thread_local_fix double reg_access_start=0.0;
__thread_local_fix double reg_access_end=0.0;

#endif
extern unsigned long buil_prof[N_BUILD_PROF];
// unsigned long add_succ_start;
#endif
void init_slave_buffer()
{
    int i;
    for(i=0;i<NT;i++){
       slave_buffer[i].head=0;
       slave_buffer[i].tail=0;
    }
}
#ifdef DISTRIBUTE_TOP
void init_tl_buffer()
{
    int i;
    for(i=0;i<NT;i++){
       tl_buffer[i].head=0;
       tl_buffer[i].tail=0;
    }
}
#endif
bool task_exists(struct task** array, int size, struct task* task) {  
    for (int i = 0; i < size; i++) {  
        if (array[i]== task) {  
            return true;  
        }  
    }  
    return false;  
}  
struct task *merge_and_deduplicate(struct task** a, int size_a, struct task** b, int size_b, int* result_size) {  
    struct task* temp[4096];  
    int index = 0;  
  
    int i = 0, j = 0;  
    while (i < size_a && j < size_b) {  
        if (i < j) {  
            if (!task_exists(temp, index, a[i])) {  
                temp[index++] = a[i];  
            }  
            i++;  
        } else if (i> j) {  
            if (!task_exists(temp, index, b[j])) {  
                temp[index++] = b[j];  
            }  
            j++;  
        } else {  // a[i]->id == b[j]->id  
            if (!task_exists(temp, index, a[i])) {  
                temp[index++] = a[i];  
            }  
            i++;  
            j++;  
        }  
    }  
  
    while (i < size_a) {  
        if (!task_exists(temp, index, a[i])) {  
            temp[index++] = a[i];  
        }  
        i++;  
    }  
  
    while (j < size_b) {  
        if (!task_exists(temp, index, b[j])) {  
            temp[index++] = b[j];  
        }  
        j++;  
    }  
  
    *result_size = index;  
		printf("归并后的大小%d\n",index);
    return temp;  
}  
// 查找公共结构体地址的函数  
// struct task** find_common_tasks(struct task *latent_top[HELPER_NUM][4096],int buffer_sizes[HELPER_NUM], int *common_count) {  
//     int arrays_count = 8;  
//     int array_size = 4096;  
//     int indices[arrays_count] = {0}; // 每个数组的当前索引  
//     struct task **common_tasks = [64]; // 存储公共任务地址的数组（动态分配）  
//     int common_index = 0; // 公共任务数组的当前索引  
  
//     // 遍历所有数组直到至少一个数组结束  
//     while (true) {  
//         struct task *min_task = NULL; // 当前最小的任务（用于比较）  
//         int min_index = -1; // 最小任务所在的数组索引  
  
//         // 找到当前所有数组中的最小任务  
//         for (int i = 0; i < arrays_count; i++) {  
//             if (indices[i] < array_size) {  
//                 if (min_task == NULL || latent_top[i][indices[i]] < min_task) {  
//                     min_task = latent_top[i][indices[i]];  
//                     min_index = i;  
//                 } else if (latent_top[i][indices[i]] == min_task) {  
//                     // 如果找到相同的任务，则标记为公共任务（需要进一步检查）  
//                     bool is_common = true;  
//                     for (int j = 0; j < arrays_count; j++) {  
//                         if (j != i && (indices[j] >= array_size || latent_top[j][indices[j]] != min_task)) {  
//                             is_common = false;  
//                             break;  
//                         }  
//                     }  
//                     if (is_common) {  
//                         // 动态分配内存以存储公共任务地址（需要释放）  
//                        // common_tasks = realloc(common_tasks, sizeof(task*) * (common_index + 1));  
//                         common_tasks[common_index++] = min_task;  
//                     }  
//                 }  
//             }  
//         }  
  
//         // 如果没有找到公共任务，并且至少有一个数组已经遍历完，则退出循环  
//         if (min_index == -1 || (min_index >= 0 && ++indices[min_index] >= array_size && !contains_common_after(latent_top, indices, arrays_count, array_size))) {  
//             break;  
//         }  
//     }  
  
//     *common_count = common_index;  
//     return common_tasks;  
// }  
  
// void init_buffer_tasks() {  
//     for (int i =0; i <= NT; i++) {  
//         buffer_tasks_list[i].head = NULL;  
//         buffer_tasks_list[i].tail = NULL;  
//     }  
// }
void add_succ(struct DataAccess *succ_access, struct DataAccess *pre_access,int id)
{
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    add_succ_start=rtc();
		// unsigned long addsucc_start=rtc();
#endif
     //printf("tbl任务类型%dtblDA地址%p任务地址%ptbl任务地址%p,\n",tbl->data_access->_type,tbl->data_access,data_access->_originator,tbl->data_access->_originator);
    if(pre_access!=NULL){
        if(pre_access->_type==IN && succ_access->_type==IN && pre_access->_accessFlags==SATISFIED){   //识别第一层，前驱是已经就绪的R，新增加剧的R也是自然就绪的，仅连接不阻塞
            slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
            slave_set_unblock_Successor(pre_access,succ_access); //R1-R2,R1是top，R2为ready
#ifdef DISTRIBUTE_TOP
						//数据流地址顺序注册，当前是top后面就不会变为succ
						//将cur_top task发给id+1号从核，让其去识别final top task
					struct top_level_buff *cur_top=remote_ldm(id+1,tl_buffer[_MYID]);
						int local_tail=(cur_top->tail+1)%HELPER_BUFF_SIZE; 
              //队列满就一直循环等待
             while(cur_top->head==local_tail){
             }  
						cur_top->top_task[cur_top->tail]=succ_access->_originator;
						cur_top->tail=local_tail;
						//printf("top任务%p从核%d的top个数%d\n",succ_access->_originator,_MYID,local_tail);
#endif  
				//  asm volatile ("memb\n");
					 // printf("不阻塞的前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator);
         }else { // 以上三个条件，任一不满足，都说明存在实际的依赖（R-W，W-R，W-W，W-R-R），必须修改引用计数
            slave_setSuccessor(pre_access,succ_access);   
						// asm volatile ("memb\n");
           // printf("前驱子任务%p,后继子任务%p\n",predata_access->_originator,data_access->_originator); 
        }   

    }else{
        if(succ_access->_type==IN){ //该地址没有前驱，且类型为读，则设置addr.top=true
            slave_set_access_state(1, &(succ_access->top));
						// asm volatile ("memb\n");
       // printf("设置%p为top%d\n",data_access,data_access->top);
        }
        slave_set_access_state(SATISFIED, &(succ_access->_accessFlags));
#ifdef DISTRIBUTE_TOP
						//数据流地址顺序注册，当前是top后面就不会变为succ
					struct top_level_buff *cur_top=remote_ldm(id+1,tl_buffer[_MYID]);
						int local_tail=(cur_top->tail+1)%HELPER_BUFF_SIZE; 
              //队列满就一直循环等待
             while(cur_top->head==local_tail){
             }  
						cur_top->top_task[cur_top->tail]=succ_access->_originator;
						cur_top->tail=local_tail;
						//printf("top任务%p从核%d的top个数%d\n",succ_access->_originator,_MYID,local_tail);
#endif
}
    //printf("设置succ\n");
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    //  buil_prof[SUB_ADD_SUCC]+=(rtc()-addsucc_start);
		 add_succ_end=rtc();
		all_pure_addsucc_time[_MYID]+=(double)(add_succ_end-add_succ_start)/SFREQ;
#endif
}

inline struct new_slave_table_item * new_get_collision_buffer_item(struct new_slave_table *addresses)
{
    //printf("addresses->col_idx %d\n",addresses->col_idx );
    assert(addresses->col_idx  < COLLISION_BUF_SIZE);
       if (addresses->col_idx >= COLLISION_BUF_SIZE) {
        int i;
        int empty = 0;
        for (i = 0; i < SLAVE_TBL_SIZE; i++) {
            if (addresses->items[i].data_addr == NULL) {
                empty++;
            }
        }
        printf("empty rate: %f\n", (float)empty / SLAVE_TBL_SIZE);
        fflush(stdout);
        // assert(0);
    }
   struct new_slave_table_item * item = &(addresses->col_items[addresses->col_idx]);
    addresses->col_idx++;
    return item;
}
void helper_reigister_access(struct slave_helper_item *item){

// typedef struct slave_helper_item {  //消息传递五元组
//     volatile void *item_address;
//     volatile struct DataAccess *item_access;
//     volatile struct task *item_task;
//     volatile int type;  
//     volatile int item_id;
// } slave_helper_item;  //依赖域哈希表
		//获取依赖分析需要的各种信息
#ifdef MULZTI_CORE_C
		void *address=item->item_address;
		struct DataAccess *access=item->item_access;
		aceMesh_task *cur_task=(aceMesh_task *)item->item_task;
		int type=item->item_type;
		int id=item->item_id;  //分布式哈希表要用
    slave_initialize(access,type,&(cur_task->task_base),INITED,0);
		unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
		aceMesh_task *parent=slave_getparent(&(cur_task->task_base));
		
#else
		void *address=item->item_address;
		unsigned long hash_value=item->item_hash;
		struct DataAccess *access=item->item_access;
		int id=item->item_id;
		aceMesh_task *cur_task=access->_originator;
		 aceMesh_task *parent=slave_getparent(&(cur_task->task_base));
#endif
		struct DataAccess *predecessor=NULL;

		//当前任务，以及当前复合任务

		//printf("地址%p,子任务%p,父任务%p\n",address,cur_task,parent);
		//复合任务、及对应哈希表
		struct TaskDataAccesses *parentAccessStruct = slave_getDataAccesses(&(parent->task_base));
		volatile struct new_slave_table *addresses = parentAccessStruct->_subaccessBottomMap;

		int tbl_idx = 0;
		//unsigned long hash_value = (unsigned long)address * HASH_MULT_VALUE;
			tbl_idx = ((hash_value) >> 44) & 0xffff; ////取高20位(高位的变化更大)中的低16位，65536
		// printf("%p更新DA地址%ptbl地址%p,\n",tbl->data_access,access->_originator,tbl->data_access->_originator);
		if (addresses->items[tbl_idx].data_addr == address) {  //哈希表存在地址
					predecessor=addresses->items[tbl_idx].data_access;
						slave_add_succ(access, predecessor,id);
							addresses->items[tbl_idx].data_access=access; //更新哈希表
							asm volatile ("memb\n");
				}
				else if (addresses->items[tbl_idx].data_addr == NULL) { //哈希表不存在此地址
						predecessor=addresses->items[tbl_idx].data_access; //NULL
						addresses->items[tbl_idx].data_addr = address;
						slave_add_succ(access, predecessor,id);
						addresses->items[tbl_idx].data_access=access; //更新哈希表
						asm volatile ("memb\n");
				}
				else {
						//printf("哈希冲突%p\n",address);
						struct new_slave_table_item * col_item = NULL;
						struct new_slave_table_item * temp = &(addresses->items[tbl_idx]);
						while (temp->succ != NULL) { 
								//struct new_slave_table_item *temp_item=NULL;
								//temp_item=temp->succ;
								if (temp->succ->data_addr == address) {  
										predecessor=temp->succ->data_access;
										slave_add_succ(access, predecessor,id);
										temp->succ->data_access=access; //更新哈希表
										asm volatile ("memb\n");
										goto update_complete;
								}
								temp = temp->succ;   
						
						}     
						 collision_item_count++; 
						col_item = new_get_collision_buffer_item(addresses);    
						temp->succ = col_item;
						col_item->data_addr = address;
						//slave_new_update_hashitem(access, col_item);
						predecessor=col_item->data_access;
						slave_add_succ(access, predecessor,id); //依赖边追加和前驱计数更新
						col_item->data_access=access; //更新哈希表
				update_complete:
						;
			
				}

			// printf("子任务前驱计数task%p,precount:%d\n",cur_task,cur_task->task_base._predecessorCount);
}
__thread_local_fix int index_id=0;

void worker_help_func()
{
#ifdef DEBUG_PBH
	printf("%dhelper轮询开始\n",_MYID);
  fflush(stdout);

#endif

		int builder_finished = 0;		
		int close=0;
		int exit=0;
    struct slave_helper_item * buff_item=NULL;    
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
    reg_access_start=rtc();
		unsigned long add_succ_start=rtc();
#endif
    while (!close_helper) { //一直轮转，至64个buffer全部为空
		struct slave_help_buff* self=NULL;
    int local_head=0,i;
		int id=_MYID;
    struct slave_helper_item *buff_item=NULL;
		for(i=0; i<NT; i++){ //一对一模式，虽然轮转64个buffer，但取的只有buffer1
    self=&slave_buffer[(i + index_id)%NT];  //当前从核的环形队列
		int buffer_id=(i + index_id)%NT;
		local_head=self->head;
		//printf("****接收****头指针%d,尾指针%d\n",local_head,self->tail);
		if(self->tail==local_head){//当从核环形队列没有元素，则查找下一个队列

		    continue;
		}
		buff_item=&(self->base[local_head]);  //接收建边需要的数据流地址信息
		// void *address=buff_item->item_address;
#ifdef MULZTI_CORE_C
    int exit_type=buff_item->item_type;
		if(exit_type==7){ //buffer接收到终止消息,等于1是因为终止消息的hash为1
		
#else
	   int hash=buff_item->item_hash;
		if(hash==1){ //buffer接收到终止消息,等于1是因为终止消息的hash为1
#endif
			// printf("从核%d取到%d结束\n",buffer_id,local_head);
			//helper_exited[buffer_id]=1;
			int *exit_signal=remote_ldm(buffer_id, helper_exited[buffer_id]);
			*exit_signal= 1;
			//printf("从核%dbuffer%d结束%d\n",_MYID,buffer_id,helper_exited[buffer_id]);
#ifdef DEBUG_PBH
			printf("从核%dbuffer%d结束\n",_MYID,buffer_id);
                            fflush(stdout);

#endif

		}else{
		//printf("从核%d队列不为空\n",(i + index_id)%NT);
	//printf("****接收bufferid%d****头指针%d,尾指针%d\n",buffer_id,local_head,self->tail);
		slave_helper_reigister_access(buff_item); //依赖分析，建边
		}
		self->head=(local_head+1)%HELPER_BUFF_SIZE;  //head指针+1，取下一个元素
		index_id++;
		}
       // slave_get_elem_from_build_and_analysis(builder_finished);       
    }   
		close_helper=0;
		printf("MYID%dcollision_item_count%d\n",_MYID,collision_item_count);
// #ifdef DEBUG_PBH
	//  printf("%dhelper轮询终止\n",_MYID);
  //   fflush(stdout);

// #endif
#if defined(ACEMESH_GRAPH_BUILD_PROFILING) && defined(FINE_PROF)
//builder从开始发送消息到等待helper全部构图结束的时间
//包含打包，发送，helper做DU、E，结束条件判断

    buil_prof[SUB_ADD_SUCC]+=(rtc()-add_succ_start);

    reg_access_end=rtc();
    all_pure_register_time[_MYID]+=(double)(reg_access_end-reg_access_start)/SFREQ;
#endif
}
